package gm.server;

import gm.server.geom.Circle;
import gm.server.geom.CircleCircleIntersection;
import gm.server.geom.Vector2;

/**
 * Végpont.
 *
 * @author imruf84
 */
public class Tip {

    /**
     * Csavar.
     */
    private final Nut nut;
    /**
     * Csavartól való távolság.
     */
    private final double nutDitsance;
    /**
     * Fej.
     */
    private final Head head;
    /**
     * Fejtől való távolság.
     */
    private final double headDistance;

    /**
     * Konstruktor.
     *
     * @param nut csavar
     * @param nutDitsance csavartól való távolság
     * @param head fej
     * @param headDistance fejtől való távolság
     */
    public Tip(final Nut nut, double nutDitsance, final Head head, double headDistance) {
        this.nut = nut;
        this.nutDitsance = nutDitsance;
        this.head = head;
        this.headDistance = headDistance;
    }

    /**
     * Fej lekérdezése.
     *
     * @return fej
     */
    public Head getHead() {
        return head;
    }

    /**
     * Kar lekérdezése.
     *
     * @return kar
     */
    public final Arm getArm() {

        if (getHead().getArm1().getNut().equals(nut)) {
            return getHead().getArm1();
        }

        return getHead().getArm2();
    }

    /**
     * Pozíció meghatározása a motorokhoz képest.
     *
     * @return pozíció a motorokhoz képest
     * @throws gm.server.WrongPositionException kivétel
     */
    public Vector2 calculatePositionLocal() throws WrongPositionException {

        Vector2 hPos = getHead().calculatePositionLocal();
        Vector2 nPos = new Vector2(getArm().getNut().getRod().getPosition(), getArm().getNut().calculatePositionAbsolute());

        CircleCircleIntersection cci = new CircleCircleIntersection(
                new Circle(hPos, headDistance),
                new Circle(nPos, nutDitsance)
        );

        Vector2 ip[] = cci.getIntersectionPoints();

        if (0 == ip.length) {
            throw new WrongPositionException(
                    getHead().getArm1().getNut().getRod().getMotor().getCurrentStepsAbsolute(),
                    getHead().getArm2().getNut().getRod().getMotor().getCurrentStepsAbsolute()
            );
        }

        if (1 == ip.length) {
            return ip[0];
        }

        int index = (!Vector2.isCW(nPos, hPos, ip[0]) ? 0 : 1);

        return ip[index];
    }

    /**
     * Pozíció meghatározása az origóhoz képest.
     *
     * @return pozíció az origóhoz képest
     * @throws gm.server.WrongPositionException kivétel
     */
    public Vector2 calculatePositionGlobal() throws WrongPositionException {

        Vector2 l = calculatePositionLocal();

        return new Vector2(l.x, getArm().getNut().getRod().getLength() - l.y);
    }

}
